package filehandler

import (
	"bufio"
	"fmt"
	"gitee.com/mjun1833/buildnotification/utils/dgfile/loggo"
	"io"
	"os"
	"sync"
	"time"
)

type fileHandler struct {
	scanner      *FileScanner
	qpsLog       *loggo.Logger
	runLog       *loggo.Logger
	costTime     int64 // micro seconds
	lineCount    int64
	bytesToPrint int64
}

func (p *fileHandler) initLogger(index int) {
	p.qpsLog = &loggo.Logger{}
	p.qpsLog.SetWriter(&loggo.FileWriter{
		FileName: fmt.Sprintf("./log/scanner-%s/handler-%d/qps.log", p.scanner.FileType, index),
		Compress: true,
	})
	p.runLog = &loggo.Logger{}
	p.runLog.SetWriter(&loggo.FileWriter{
		FileName: fmt.Sprintf("./log/scanner-%s/handler-%d/run.log", p.scanner.FileType, index),
		Compress: true,
	})
}
func (p *fileHandler) HandleFile(removeHandledFile bool, fileName string, oldCursor int64, handlerCh chan *fileHandler, wg *sync.WaitGroup) error {
	defer func() {
		handlerCh <- p
		wg.Done()
	}()
	if fileName == "" {
		return nil
	}
	f, err := os.Open(fileName)
	if err != nil {
		p.runLog.Errorln("open error,", err.Error())
		return err
	}
	defer f.Close()

	if !IsFileWriteFinish(f) {
		p.runLog.Errorln("File still writting,HANDLE ABORT :", fileName)
		return nil
	}

	var count, newCursor, fileSize, lineSum, sum int64
	stat, err := f.Stat()
	if err == nil {
		fileSize = stat.Size()
	} else {
		p.runLog.Errorln(err.Error())
		return err
	}

	m := fmt.Sprintf("------ Start  handleFile: %s\t%s", formatSize(fileSize), fileName)
	p.runLog.Infoln(m)
	//if strings.Contains(m, "/data1") {
	//	sender.DingtalkMsg(m)
	//}

	if err != nil {
		p.runLog.Errorln("parse int64 error")
		return err
	}

	if oldCursor != 0 {
		f.Seek(oldCursor, 0)
		newCursor += oldCursor
	}

	st := time.Now()
	buff := bufio.NewReader(f)
	for {
		line, err := buff.ReadBytes('\n')
		if err == io.EOF {
			break
		}

		l := int64(len(line))
		sum += l
		count += l
		newCursor += l
		lineSum++
		p.lineCount++
		if count >= p.bytesToPrint {
			p.printProgress(fileName, st, lineSum, sum, newCursor, fileSize)
			p.scanner.statusChange(fileName, newCursor)
			count = 0
		}

		t0 := time.Now()
		if p.scanner.HandleByteFuncByFileName != nil {
			p.scanner.HandleByteFuncByFileName(line, []byte(fileName))
		} else if p.scanner.HandleByteFunc != nil {
			p.scanner.HandleByteFunc(line)
		} else if p.scanner.HandleLineFunc != nil {
			p.scanner.HandleLineFunc(string(line))
		} else {
			panic("Please set the func to handle a row of data")
		}
		p.costTime += time.Now().Sub(t0).Microseconds()
	}
	p.printProgress(fileName, st, lineSum, sum, newCursor, fileSize)
	p.scanner.statusChange(fileName, -1)
	p.runLog.Infofn("------ Finish handleFile: %s\t%s", formatSize(fileSize), fileName)
	if removeHandledFile {
		if err := os.Remove(fileName); err != nil {
			p.runLog.Errorln("remove file error", err.Error())
			return err
		}
	}
	return nil
}

func IsFileWriteFinish(f *os.File) bool {
	stat, err := f.Stat()
	if err != nil {
		return false
	}
	size1 := stat.Size()
	time.Sleep(10 * time.Millisecond)
	stat, err = f.Stat()
	if err != nil {
		return false
	}
	size2 := stat.Size()
	return size1 == size2
}
